function [lpostmin,xmax,exitflag,output,tiempo,iterations,Hx]=...
    estima_fmincon_central(x0,parvec,parposest,funcmod,Y,trainvec,prpar,prss,solveopt,addsol,ssposest,estimopt)
% ======================================================================
% ESTIMA_FMINCON_CENTRAL.M
%
% Uses FMINCON optimization routine 
% CENTRAL since it allows for time aggregation issues, using same set-up as
% LMJ_LIKEL_CENTRAL.m 
% Function underlying minization is identical to LMJ_POSTOPTIM.m and is
% included as a nested function. Only difference is that the parameter does 
% not go through the transformation matrix since the bounds are directly applied to the optimization 
% procedure using BOUNDS loaded from prior. 
% Hence X0 is an unstransformed starting value 
% format.  
%
% Input 
% ------
% Note:     Input PRPAR.LBND and PRPAR.UBND is truncated inside code 
% ESTIMOPT  Has all the settings for the optimization  
% Output 
% ------
% XMIN      in MIN  space for compatibility with GENSYSOUTPUT 
% XMODEL    in MODEL space  
% LPOSTMIN  stil *(-1) 
% Using OUTPUT, will display end message in a DIARY file created in the
% output subdirectory 
% 
% Alejandro Justiniano  January 11 2008 
% 1/13/09 Added LBND and UBND in priordens s.t. can work with the truncated
% BETA 
% 6/27/09 Added mixed frequency 
%         For faster speed could code a routine for each case 
%         FLAG_OK == 1 for solution to be valid 
% =======================================================================
clear x lpostd; 
if any(imag(x0)~=0);error('Initial guess X0 cannot be imaginary');end
% Truncate bounds 
% ========================================================================
% Define the bounds for the optimization to ensure compatibility with
% INDMAT. Also check suggested starting point is within bounds, else adjust
% BOUNDS should NOT be truncated 
% ========================================================================
offset=1e-8; 
bounds=[prpar.lbnd(parposest)+offset prpar.ubnd(parposest)-offset]; 
check1=find(x0 < bounds(:,1));
check2=find(x0 > bounds(:,2)); 
if ~isempty(check1) 
    check1_disc=abs(x0(check1)-prpar.lbnd(check1)); 
    if max(check1_disc) > 0.01;error('Starting value is below lower bound');end
    x0(check1)=x0(check1)+check1_disc+offset; 
end 
if ~isempty(check2) 
    check2_disc=abs(x0(check2)-prpar.ubnd(check2)); 
    if max(check2_disc) > 0.01;
        dispaj('Positions ',check2(:),' above upper bound')
        error('Starting value is above upper bound')
    end
    x0(check2)=x0(check2)-check2_disc-offset;
end 
clear check* offset; 
% ========================================================================
% Begin Optimization  
% ========================================================================
tic;
[xmax,lpostmin,exitflag,output,~,~,Hx]=fmincon(@lmj_postoptimsub,x0,[],[],[],[],bounds(:,1),bounds(:,2),[],estimopt);
tiempo=toc; 
iterations=output.iterations;
% ============================================
%           NESTED FUNCTION
% ============================================
    function lpostd=lmj_postoptimsub(x) 
        lpostd=1e20;
        parvec(parposest)=x;        

        % 1. Log Likelihood, with normalizing constant included
        switch addsol.flag_mixfreq
            case 0
                [lht,ssvec,flag_ok] = lmj_likel(x, parvec, parposest, funcmod, Y, trainvec,solveopt, addsol);
            case 1
                if addsol.flag_gtv == 1
                    [lht, ssvec,flag_ok] = lmj_likel_tagtv_general(x, parvec, parposest, funcmod, Y, trainvec, solveopt, addsol);
                else
                    [lht, ssvec,flag_ok] = lmj_likel_tagin(x, parvec, parposest, funcmod, Y, trainvec, solveopt, addsol);
                end
        end
        if flag_ok==0;
            return
        end

        % 2. Prior for the parameters
        lpriord=sum(priordens(parvec,prpar.prior,prpar.alphap,prpar.betap,prpar.lbnd,prpar.ubnd));
        if isinf(abs(lpriord))==1;disp('Prior is INF');return;end
        
        % 3. Prior for the SS 
        if ~isempty(ssposest)
            lpriord_ss = sum(priordens(ssvec(ssposest), prss.prior, prss.alphap, prss.betap, prss.lbnd, prss.ubnd));
        else
            lpriord_ss=0;
        end
        
        lpostd=-(lpriord+lpriord_ss+lht); 
        %disp(['LPOSTD=',num2str(lpostd)]); 
    end
end